package it.unisannio.lesim.fsm;

import it.unisannio.lesim.fsm.exception.UnrecognizedTokenException;

/**
 *
 * @author Marco Calisti
 * @author Antonio Cuomo
 * @author Rocco Mazzeo
 * @author Francesco Pacilio
 * 
 */

class MyTokenizer {
    
    public static final int NOT_STARTED= 0;
    public static final int END_REACHED= 1;
    public static final int LEFT_ROUND_PAR= 2;
    public static final int RIGHT_ROUND_PAR= 3;
    public static final int LEFT_SQUARE_PAR= 4;
    public static final int RIGHT_SQUARE_PAR= 5;
    public static final int AND_OPERATOR= 6;
    public static final int OR_OPERATOR= 7;
    public static final int NOT_OPERATOR= 8;
    public static final int CONSTANT_VALUE= 9;
    public static final int STRING= 10;
    public static final int MESSAGE_KIND= 11;
    public static final int MESSAGE_FIELD= 12;
    public static final int MESSAGE_FIELD_OPTION= 13;
    public static final int TIME= 14;
    public static final int EQUALITY_OPERATOR= 15;
    public static final int DISEQUALITY_OPERATOR= 16;
    public static final int LT_OPERATOR= 17;
    public static final int GT_OPERATOR= 18;
    public static final int LE_OPERATOR= 19;
    public static final int GE_OPERATOR= 20;
    public static final int READ_FIELD_COMMAND= 21;
    public static final int EXIST_FIELD= 22;
    public static final int TIME_DIFF= 23;  
    

    private String expression;
    private int kind;
    private String lexeme;
    
    public MyTokenizer(String expression) {
        this.expression= expression.trim();
        this.kind=NOT_STARTED;
        this.lexeme=expression;
    }
    
    
    public void consumeToken() throws UnrecognizedTokenException {
        if(expression.length()==0){
            kind=END_REACHED;
            lexeme="";
            return;
        }
        //Check this before declaring ! as the NOT OPERATOR
        else if(expression.startsWith("!=")){
            kind= DISEQUALITY_OPERATOR;
            lexeme= expression.substring(0, 2);
            expression = expression.substring(2).trim();
            return;
        }
        
        char firstChar=expression.charAt(0);
        //Handle single char tokens
        switch(firstChar){
            case '(' :    kind= LEFT_ROUND_PAR;lexeme=expression.substring(0, 1); expression=expression.substring(1).trim(); return; 
            case ')' :    kind= RIGHT_ROUND_PAR;lexeme=expression.substring(0, 1); expression=expression.substring(1).trim(); return;
            case '[' :    kind= LEFT_SQUARE_PAR;lexeme=expression.substring(0, 1);expression=expression.substring(1).trim();return;
            case ']' :    kind= RIGHT_SQUARE_PAR;lexeme=expression.substring(0, 1);expression=expression.substring(1).trim(); return;
            case '!'  :   kind= NOT_OPERATOR;lexeme=expression.substring(0, 1);expression=expression.substring(1).trim(); return;
            case '\'' :   kind= CONSTANT_VALUE; expression=expression.substring(1);handleDelimitedSequence('\'');return;
            case '\"' :   kind= STRING; expression=expression.substring(1); handleDelimitedSequence('\"');return;
        }
        
        if(expression.startsWith("&&")){    
            kind= AND_OPERATOR;
            lexeme= expression.substring(0, 2);
            expression = expression.substring(2).trim();
        }
        else if(expression.startsWith("||")){
            kind= OR_OPERATOR;
            lexeme= expression.substring(0, 2);
            
        }
        else if(expression.startsWith(">=")){
            kind= GE_OPERATOR;
            lexeme= expression.substring(0, 2);
            expression = expression.substring(2).trim();
        }
        else if(expression.startsWith(">")){
            kind= GT_OPERATOR;
            lexeme= expression.substring(0, 1);
            expression = expression.substring(1).trim();
        }
        else if(expression.startsWith("<=")){
            kind= LE_OPERATOR;
            lexeme= expression.substring(0, 2);
            expression = expression.substring(2).trim();
        }
        else if(expression.startsWith("<")){
            kind= LT_OPERATOR;
            lexeme= expression.substring(0, 1);
            expression = expression.substring(1).trim();
        }
        else if(expression.startsWith("==")){
            kind= EQUALITY_OPERATOR;
            lexeme= expression.substring(0, 2);
            expression = expression.substring(2).trim();
        }
        else if(expression.startsWith("messageKind")){
            kind= MESSAGE_KIND;
            lexeme= expression.substring(0, "messageKind".length());
            expression = expression.substring("messageKind".length()).trim();
        }
        else if(expression.startsWith("messageField")){
             kind= MESSAGE_FIELD;
            lexeme= expression.substring(0, "messageField".length());
            expression = expression.substring("messageField".length()).trim();
        
        }
        else if(expression.startsWith("messageFieldOption")){
             kind= MESSAGE_FIELD_OPTION;
            lexeme= expression.substring(0, "messageFieldOption".length());
            expression = expression.substring("messageFieldOption".length()).trim();
        }
        else if(expression.startsWith("timeDiff")){
             kind= TIME_DIFF;
            lexeme= expression.substring(0, "timeDiff".length());
            expression = expression.substring("timeDiff".length()).trim();
        }
        else if(expression.startsWith("time")){
             kind= TIME;
            lexeme= expression.substring(0, "time".length());
            expression = expression.substring("time".length()).trim();
        }
        else if(expression.startsWith("readField")){
             kind= READ_FIELD_COMMAND;
            lexeme= expression.substring(0, "readField".length());
            expression = expression.substring("readField".length()).trim();
        }
        else if(expression.startsWith("existField")){
             kind= EXIST_FIELD;
            lexeme= expression.substring(0, "existField".length());
            expression = expression.substring("existField".length()).trim();
        }
        else
            throw new UnrecognizedTokenException();
    }
    
    private void handleDelimitedSequence(char delimiter) throws UnrecognizedTokenException {
       int closingIndex = expression.indexOf(delimiter);
       if(closingIndex == -1)
           throw new UnrecognizedTokenException();
       lexeme = expression.substring(0, closingIndex);
       expression = expression.substring(closingIndex+1);
    }
    
    public int lastTokenType(){
        return kind;
    }
    
    public String lastLexeme(){
        return lexeme;
    }
}
